
#include <cmath>

#include "ddc_math.h"

// class DDC_Vector2 {

const DDC_Vector2 DDC_Vector2::UP = DDC_Vector2(0, 1);
const DDC_Vector2 DDC_Vector2::DOWN = DDC_Vector2(0, -1);
const DDC_Vector2 DDC_Vector2::LEFT = DDC_Vector2(-1, 0);
const DDC_Vector2 DDC_Vector2::RIGHT = DDC_Vector2(1, 0);

// } class DDC_Vector2

// class DDC_Tuple2 {

const DDC_Tuple2 DDC_Tuple2::EMPTY = DDC_Tuple2(1, -1);

// } class DDC_Tuple2

DDC_Tuple2 DDC_Math::Intersection(DDC_Tuple2 rangeA, DDC_Tuple2 rangeB) {
    DDC_Tuple2 *left, *right;

    DDC_Tuple2 result;

    if (rangeA.a > rangeB.a) {
        right = &rangeA;
        left = &rangeB;
    } else {
        right = &rangeB;
        left = &rangeA;
    }

    if (left->b < right->a)
        return DDC_Tuple2::EMPTY;

    result.a = right->a;
    result.b = std::min(left->b, right->b);

    return result;
}

bool DDC_Math::RectIntersect(DDC_FRect rectA, DDC_FRect rectB) {
    if (Intersection(
                     DDC_Tuple2(rectA.x, rectA.x + rectA.width),
                     DDC_Tuple2(rectB.x, rectB.x + rectB.width)
                     ).IsEmpty())
        return false;

    if (Intersection(
                     DDC_Tuple2(rectA.y, rectA.y + rectA.height),
                     DDC_Tuple2(rectB.y, rectB.y + rectB.height)
                     ).IsEmpty())
        return false;

    return true;
}

bool DDC_Math::RectIntersect(DDC_Rect rectA, DDC_Rect rectB) {
    return RectIntersect(DDC_RectToFRect(&rectA), DDC_RectToFRect(&rectB));
}

float DDC_Math::RectDistance(DDC_FRect rectA, DDC_FRect rectB) {
    return std::sqrt(std::pow(rectA.x - rectB.x, 2) + std::pow(rectA.y - rectB.y, 2));
}

float DDC_Math::RectDistance(DDC_Rect rectA, DDC_Rect rectB) {
    return RectDistance(DDC_RectToFRect(&rectA), DDC_RectToFRect(&rectB));
}
